package com.wzk.travelspringboot.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.wzk.travelspringboot.common.LogToFile;
import com.wzk.travelspringboot.common.RedisConstant;
import com.wzk.travelspringboot.dao.*;
import com.wzk.travelspringboot.dto.BlogLikedDTO;
import com.wzk.travelspringboot.dto.Result;
import com.wzk.travelspringboot.entity.*;
import com.wzk.travelspringboot.service.BlogService;
import com.wzk.travelspringboot.utils.MinioUtil;
import com.wzk.travelspringboot.vo.BlogCommentVO;
import com.wzk.travelspringboot.vo.BlogVO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.swing.*;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.logging.Logger;

/**
 * @Author: WangZiKang
 * @Date: 2025/1/15 21:09
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class BlogServiceImpl extends ServiceImpl<BlogDAO,Blog> implements BlogService {

    private final BlogDAO blogDAO;

    private final MinioUtil minioUtil;

    private final BlogImgDAO blogImgDAO;

    private final BlogCommentDAO blogCommentDAO;

    private final UserDAO userDAO;

    private final StringRedisTemplate stringRedisTemplate;

    private final BlogLikeDAO blogLikeDAO;

    public static final Logger logger = Logger.getLogger(BlogServiceImpl.class.getName());

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result publishBlog(long userId,String content, MultipartFile[] files) {
       try{
           //0.保存发布的动态数据
           Blog blog = new Blog();
           blog.setContent(content);
           blog.setUserId(userId);
           blog.setLikeTotal(0L);
           blog.setCreateTime(LocalDateTime.now());
           blog.setUpdateTime(LocalDateTime.now());
           boolean res = save(blog);
           if (!res){
               return Result.failed("发布动态失败！出现未知错误请联系管理员");
           }
           if (files != null && files.length > 0){
              //1.检测文件类型
              for (MultipartFile file : files) {
                  //1.1.判断文件类型是否合法
                  boolean b = minioUtil.checkFileSuffix(file.getOriginalFilename());
                  if (!b){
                      return Result.failed("文件不合法！");
                  }
                  //1.2.上传文件并返回浏览路径
                  String fileUrl = minioUtil.uploadImageFile("avatar", file.getOriginalFilename(), file.getInputStream());
                  //1.3保存到数据库
                  BlogImg blogImg = new BlogImg();
                  blogImg.setImgUrl(fileUrl);
                  blogImg.setBlogId(blog.getId());
                  blogImg.setCreateTime(LocalDateTime.now());
                  blogImg.setUpdateTime(LocalDateTime.now());
                  blogImgDAO.insert(blogImg);
              }
           }
            //2.返回结果
           return Result.success("发布成功！");
       }catch (Exception e){
           LogToFile.logToFile("publishBlog出现异常，信息:"+e.getMessage(),logger,"blog_publish_err");
           //捕获异常一定要抛出 不然事物不会回滚
           throw new RuntimeException(e);
       }
    }

    @Override
    public Result queryAllBlog() {
        //1.查询所有动态按照时间降序 在按照点赞量降序
        List<Blog> blogs = query().ne("is_delete",1).orderByDesc("create_time").orderByDesc("like_total").list();
        if (!blogs.isEmpty()){
            //2.查询每个动态的所有图片 以及每个动态下面所有的评论数据
            List<BlogVO> vos = new ArrayList<>(blogs.size());
            for (Blog blog : blogs) {
                BlogVO blogVO = new BlogVO();
                blogVO.setId(blog.getId());
                blogVO.setCreateTime(blog.getCreateTime());
                blogVO.setIsLiked(true);
                //判断当前登录的用户是否点赞过这个动态
                Boolean b = stringRedisTemplate.opsForSet().isMember(RedisConstant.BLOG_LIKE_KEY + blog.getId(), 1 + "");
                if (Boolean.FALSE.equals(b)){
                    blogVO.setIsLiked(false);
                }else {
                    blogVO.setIsLiked(true);
                }
                blogVO.setImages(new ArrayList<>());
                blogVO.setComments(new ArrayList<BlogCommentVO>());
                //2.0查询用户的昵称和头像
                User user = userDAO.selectById(blog.getUserId());
                if (user == null){
                    blogVO.setUserId(0L);
                    blogVO.setAvatar("");
                    blogVO.setNickName("未知用户");
                }else {
                    blogVO.setUserId(user.getId());
                    blogVO.setAvatar(user.getAvatar());
                    blogVO.setNickName(user.getNickName());
                }
                blogVO.setLikeTotal(blog.getLikeTotal());
                blogVO.setContent(blog.getContent());
                //2.1查询动态下面的所有图片
                List<BlogImg> blogImgs = blogImgDAO.queryBlogImgByBlogId(blog.getId());
                if (!blogImgs.isEmpty()){
                    for (BlogImg blogImg : blogImgs) {
                        blogVO.getImages().add(blogImg.getImgUrl());
                    }
                }
                //2.2查询动态下面所有的评论
                List<BlogComment> blogComments = blogCommentDAO.queryCommentsByBlogId(blog.getId());
                //2.3插入评论数据
                if (!blogComments.isEmpty()){
                    for (BlogComment blogComment : blogComments) {
                        BlogCommentVO commentVO = new BlogCommentVO();
                        User commentUser = userDAO.selectById(blog.getUserId());
                        if (commentUser == null){
                            commentVO.setUserId(0L);
                            commentVO.setNickName("未知用户");
                        }else {
                            commentVO.setUserId(commentUser.getId());
                            commentVO.setNickName(commentUser.getNickName());
                        }
                        commentVO.setContent(blogComment.getContent());
                        blogVO.getComments().add(commentVO);
                    }
                }
                vos.add(blogVO);
            }
            return Result.success("动态数据加载成功",vos);
        }
        return Result.success(Collections.emptyList());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result isLikedBlog(long blogId, long userId) {
        //判断当前动态是否存在
        Blog blog = blogDAO.selectById(blogId);
        if (blog == null || blog.getIsDelete() == 1){
            return Result.failed("当前动态不存");
        }
        //0.对当前用户操作的blog的key加锁避免点赞数据出现错误的情况
        synchronized (RedisConstant.BLOG_LIKE_KEY+blogId){
            //1.缓存中查看当前用户是否点赞过这条动态
            Boolean b = stringRedisTemplate.opsForSet().isMember(RedisConstant.BLOG_LIKE_KEY + blogId, userId+"");
            if (Boolean.FALSE.equals(b)){
                //2.添加到缓存中 点赞+1
                stringRedisTemplate.opsForSet().add(RedisConstant.BLOG_LIKE_KEY + blogId, userId + "");
                //3.数据库点赞数+1
                int i = blogDAO.likeNumberIncr(blogId);
                if (i <= 0){
                    LogToFile.logToFile("点赞数据 ["+b+"] 更改数据库失败!blogId:"+blogId+",userId:"+userId,logger,"liked_err");
                }
                //记录用户点赞的记录
                BlogLike blogLike = new BlogLike();
                blogLike.setUserId(userId);
                blogLike.setBlogId(blogId);
                int res = blogLikeDAO.insert(blogLike);
                if (res <= 0){
                    LogToFile.logToFile("添加点赞数据失败！点赞数据:"+blogLike,logger,"liked_err");
                }
                return Result.success("点赞成功",true);
            }else {
                //4.缓存中存在当前用户的点赞数据 取消点赞 清除用户的id
                stringRedisTemplate.opsForSet().remove(RedisConstant.BLOG_LIKE_KEY+blogId,userId+"");
                //5.点赞数量-1
                int i = blogDAO.likeNumberDecr(blogId);
                if (i <= 0){
                    LogToFile.logToFile("点赞数据 ["+b+"] 更改数据库失败!blogId:"+blogId+",userId:"+userId,logger,"liked_err");
                }
                int res = blogLikeDAO.deleteBlogLike(blogId, userId);
                if (res <= 0){
                    LogToFile.logToFile("删除点赞数据失败！userId:"+userId+",blogId:"+blogId,logger,"liked_err");
                }
                return Result.success("取消点赞",false);
            }
        }
    }

    @Override
    public Result queryBlogByUserId(Long id) {
        //1.查询用户是否存在
        User user = userDAO.selectById(id);
        if (user == null || user.getState() != 1){
            return Result.failed("用户不存在或状态异常");
        }
        //2.查询用户所有的动态
        List<Blog> blogs = blogDAO.queryBlogByUserId(id);
        if (blogs.isEmpty()){
            return Result.success(Collections.emptyList());
        }
        ArrayList<BlogVO> vos = new ArrayList<>(blogs.size());
        for (Blog blog : blogs) {
            BlogVO vo = new BlogVO();
            vo.setContent(blog.getContent());
            vo.setId(blog.getId());
            vo.setUserId(blog.getUserId());
            vo.setLikeTotal(blog.getLikeTotal());
            vo.setCreateTime(blog.getCreateTime());
            //查询动态的所有图片
            List<BlogImg> blogImgs = blogImgDAO.queryBlogImgByBlogId(blog.getId());
            if (!blogImgs.isEmpty()){
                ArrayList<String> imgs = new ArrayList<>(blogImgs.size());
                for (BlogImg blogImg : blogImgs) {
                    imgs.add(blogImg.getImgUrl());
                }
                vo.setImages(imgs);
            }else {
                vo.setImages(Collections.emptyList());
            }
            vos.add(vo);
        }
        return Result.success("数据加载成功",vos);
    }

    @Override
    public Result delByBlogId(Long id) {
        //1.判断动态是否存在
        Blog blog = blogDAO.selectById(id);
        if (blog == null || blog.getIsDelete() == 1){
            return Result.failed("该动态已不存在");
        }
        //2.修改状态
        int i = blogDAO.deleteBlogById(id);
        if (i <= 0){
            return Result.failed("删除动态失败！出现未知错误请联系管理");
        }
        return Result.success("删除成功");
    }
}
